package com.bnd.service.impl;

import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bnd.common.ErrorCode;
import com.bnd.common.exception.BusinessException;
import com.bnd.common.holder.VoiceIdHolder;
import com.bnd.config.AiConfig;
import com.bnd.domain.CharacterInfo;
import com.bnd.service.CharacterInfoService;
import com.bnd.mapper.CharacterInfoMapper;
import com.bnd.service.VoiceService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.nio.ByteBuffer;


/**
 * 角色信息服务实现类
 * @author 20668
 * @description 针对表【character_info】的数据库操作Service实现
 * @createDate 2025-09-22 22:12:28
 */
@Service
@Slf4j
public class CharacterInfoServiceImpl extends ServiceImpl<CharacterInfoMapper, CharacterInfo>
    implements CharacterInfoService{
    @jakarta.annotation.Resource
    private AiConfig aiConfig;
    @jakarta.annotation.Resource
    private VoiceService voiceService;

    /**
     * 根据ID获取角色详情
     * @param id 角色ID
     * @return 角色信息
     */
    @Cacheable(value = "characterDetail", key = "#id", unless = "#result == null")
    public CharacterInfo getCharacterById(Long id) {
        log.info("[角色详情查询] id={}", id);
        CharacterInfo characterInfo = this.getById(id);
        if (characterInfo != null) {
            // 去除创建/更新时间（仅影响返回）
            characterInfo.setCreateTime(null);
            characterInfo.setUpdateTime(null);
        }
        log.info("[角色详情查询] 结果={}", characterInfo != null ? "存在" : "不存在");
        return characterInfo;
    }
    /**
     * 分页查询角色信息（带缓存）
     * @param keyword 搜索关键词，可为空
     * @param category 角色分类，传"全部"或不传表示查询所有分类
     * @param pageNum 当前页码，小于1时自动设为1
     * @param pageSize 每页数量，超出1-100范围时自动设为8
     * @return 包含分页信息的角色数据列表
     */
    @Override
    @Cacheable(value = "characterList", key = "#keyword + '_' + #category + '_' + #pageNum + '_' + #pageSize", unless = "#result == null")
    public PageInfo<CharacterInfo> pageSearch(String keyword, String category, int pageNum, int pageSize) {


    // 中文日志：记录查询条件
        String safeKeyword = StringUtils.abbreviate(StringUtils.defaultString(keyword), 100);
        log.info("[角色分页查询] keyword={}, category={}, pageNum={}, pageSize={}", safeKeyword, category, pageNum, pageSize);

        try {
            if (pageNum < 1) pageNum = 1;
            if (pageSize < 1 || pageSize > 100) pageSize = 8;
            PageHelper.startPage(pageNum, pageSize);
            if (StringUtils.equalsIgnoreCase(category, "全部")) {
                category = null;
            }
            var list = this.baseMapper.selectByCondition(StringUtils.trimToNull(keyword), StringUtils.trimToNull(category));
            // 去除创建/更新时间（仅影响返回）
            list.forEach(ci -> { if (ci != null) { ci.setCreateTime(null); ci.setUpdateTime(null); } });
            PageInfo<CharacterInfo> pageInfo = new PageInfo<>(list);
            log.info("[角色分页查询] 返回数量={}, 总数={}", list.size(), pageInfo.getTotal());
            return pageInfo;
        } catch (BusinessException e) {
            log.error("[角色分页查询] 业务异常", e);
            throw e;
        } catch (Exception e) {
            log.error("[角色分页查询] 系统异常", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "角色列表查询失败");
        }
    }

    /**
     * 角色音频播放 【SSE调用】
     * @param characterId 角色id
     * @return 角色音频
     */
    @Override
    public SseEmitter voicePlayBackWithSse(Long characterId) {
        CharacterInfo characterInfo = this.getById(characterId);
        String greeting = characterInfo.getGreeting();
        // 获取角色的音色ID【如果音色存在且合法，则使用，否则使用默认的音色】
        String voiceId = VoiceIdHolder.isValidVoiceId(characterInfo.getVoice()) ? characterInfo.getVoice() : aiConfig.getDashscope().getSsVoice();

        return voiceService.playVoice(voiceId, greeting);
    }


    /**
     * 角色音频播放 【同步调用】
     * @param characterId 角色id
     * @return 角色音频
     */
    @Override
    public ResponseEntity<Resource> voicePlayBack(Long characterId) {
        //1. 获取角色打招呼语
        CharacterInfo characterInfo = this.getById(characterId);
        String greeting = characterInfo.getGreeting();

        //2. 合成音频 (使用同步调用)
        SpeechSynthesisParam param = SpeechSynthesisParam.builder()
                .apiKey(aiConfig.getDashscope().getApiKey())
                .model(aiConfig.getDashscope().getSsModel())
                .voice(aiConfig.getDashscope().getSsVoice())
                .build();

        SpeechSynthesizer synthesizer = new SpeechSynthesizer(param, null); // 同步模式，不使用回调
        ByteBuffer audioBuffer = null;

        try {
            // 阻塞调用，直到音频返回
            audioBuffer = synthesizer.call(greeting);

            if (audioBuffer != null) {
                // 将ByteBuffer转换为byte[]
                byte[] audioData = audioBuffer.array();

                ByteArrayResource resource = new ByteArrayResource(audioData);
                return ResponseEntity.ok()
                        .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"voice.wav\"")
                        .contentType(MediaType.valueOf("audio/wav"))
                        .body(resource);
            } else {
                log.error("语音合成返回空音频数据");
            }

        } catch (Exception e) {
            log.error("语音合成或返回过程异常", e);
        } finally {
            try {
                // 任务结束后关闭websocket连接
                synthesizer.getDuplexApi().close(1000, "bye");
            } catch (Exception closeException) {
                log.warn("关闭语音合成器连接时发生异常", closeException);
            }
        }

        return null;
    }

    /**
     * 获取收藏角色列表（带缓存）
     * @return 收藏的角色列表
     */
    @Override
    @Cacheable(value = "characterFavorites", unless = "#result == null || #result.isEmpty()")
    public java.util.List<CharacterInfo> listFavorites() {
        try {
            log.info("[收藏列表] 查询收藏角色");
            java.util.List<CharacterInfo> favorites = this.baseMapper.selectFavorites();
            log.info("[收藏列表] 返回数量={}", favorites.size());
            return favorites;
        } catch (Exception e) {
            log.error("[收藏列表] 查询异常", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "获取收藏列表失败");
        }
    }

    /**
     * 清除角色列表缓存
     */
    @Override
    @CacheEvict(value = "characterList", allEntries = true)
    public void clearCharacterListCache() {
        log.info("[缓存清除] 清除角色列表缓存");
    }

    /**
     * 清除角色详情缓存
     * @param id 角色ID
     */
    @Override
    @CacheEvict(value = "characterDetail", key = "#id")
    public void clearCharacterDetailCache(Long id) {
        log.info("[缓存清除] 清除角色详情缓存, id={}", id);
    }

    /**
     * 清除收藏列表缓存
     */
    @Override
    @CacheEvict(value = "characterFavorites", allEntries = true)
    public void clearCharacterFavoritesCache() {
        log.info("[缓存清除] 清除收藏列表缓存");
    }
}




